package it.fuesi.synotools.services.tasks;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Message;
import android.util.Log;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

import javax.jmdns.JmDNS;
import javax.jmdns.NetworkTopologyDiscovery;
import javax.jmdns.ServiceInfo;

import it.fuesi.synotools.helpers.DiscoveringHandler;

/**
 * Created by pascotto on 16/11/14.
 */
public class DiscoveringTask extends AsyncTask<Void, Void, Void> {

    private Context context;

    public DiscoveringTask(Context context){
        super();
        this.context = context;
    }

    @Override
    protected Void doInBackground(Void... voids) {
        JmDNS jmdns = null;
        WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
        WifiManager.MulticastLock lock = wifi.createMulticastLock("fliing_lock");
        lock.setReferenceCounted(true);
        try {
            lock.acquire();
            InetAddress addr = getLocalIpAddress();
            jmdns = JmDNS.create(addr);
            NetworkTopologyDiscovery discovery = NetworkTopologyDiscovery.Factory.getInstance();
            for(InetAddress address : discovery.getInetAddresses()){
                Log.d("DiscoveringTask", "Topology --> " + address.getHostAddress());
            }
            ServiceInfo[] infos = jmdns.list("_http._tcp.local.");
            Message msg = new Message();
            msg.what = DiscoveringHandler.MSG_SERVER_FOUND;
            msg.obj = infos;
            Log.d("DiscoveringTask", "Found " + infos.length + " items");
            for(ServiceInfo info : infos){
                Log.d("DiscoveringTask", "What["+msg.what+"] - obj["+info.getHostAddresses()+"]");
            }

        }
        catch (SecurityException e){
            //Could not acquire lock. Fake no server found...
            ServiceInfo[] infos = new ServiceInfo[0];
            Message msg = new Message();
            msg.what = DiscoveringHandler.MSG_SERVER_FOUND;
            msg.obj = infos;
            Log.d("DiscoveringTask", "What["+msg.what+"] - obj["+infos[0].getHostAddresses()+"]");
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if (jmdns != null)
                try {
                    jmdns.close();
                }catch(IOException ioe){
                    ioe.printStackTrace();
                }
            if (lock != null) {
                if (lock.isHeld()) lock.release();
            }
        }

        return null;
    }

    /**
     * Return local IP adress. This method iterates to each network interface and
     * try to find something different that loopback address
     *
     * @return
     */
    private static InetAddress getLocalIpAddress() {
        try {
            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                NetworkInterface intf = en.nextElement();
                for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                    InetAddress inetAddress = enumIpAddr.nextElement();
                    if (!inetAddress.isLoopbackAddress()) {
                        return inetAddress;
                    }
                }
            }
        }
        catch (SocketException ex) {
            Log.e("Discovering thread", ex.toString());
        }
        return null;
    }

}
